package com.ailesson.video.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.ailesson.common.except.GlobalErrorCodeConstants;
import com.ailesson.common.except.ServiceException;
import com.ailesson.common.reply.PageResult;
import com.ailesson.video.entity.SubjectEntity;
import com.ailesson.video.listener.ReadExcelListener;
import com.ailesson.video.mapper.SubjectMapper;
import com.ailesson.video.model.dto.ExcErrorInfoDto;
import com.ailesson.video.model.dto.SubjectExcDto;
import com.ailesson.video.model.reply.SubjectReply;
import com.ailesson.video.model.req.SubjectQueryReq;
import com.ailesson.video.model.req.SubjectReq;
import com.ailesson.video.service.SubjectService;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;


@Slf4j
@Service
public class SubjectServiceImpl extends ServiceImpl<SubjectMapper, SubjectEntity> implements SubjectService {

    @Value("${import.data.batchSize:1000}")
    private Integer batchSize;

    @Override
    public PageResult queryPage(SubjectQueryReq params) {
       Page pageTmp = Page.of(params.getPageNo(),params.getPageSize());
       IPage<SubjectEntity> page = this.page(
               pageTmp,
               new LambdaQueryWrapper<SubjectEntity>().orderByDesc(SubjectEntity::getId)
       );
       List<SubjectReply> replyList = Collections.EMPTY_LIST;
       if (CollectionUtil.isNotEmpty(page.getRecords())){
           replyList = page.getRecords().stream().map(x -> {
               SubjectReply reply = new SubjectReply();
               BeanUtils.copyProperties(x, reply);
               return reply;
           }).collect(Collectors.toList());
       }
       return new PageResult<>(replyList,page.getTotal());
    }

    @Override
    public SubjectReply info(Long id) {
        SubjectEntity entity = this.getById(id);
        if (entity != null){
            SubjectReply reply = new SubjectReply();
            BeanUtils.copyProperties(entity, reply);
            return reply;
        }
        return null;
    }

    @Transactional(
            rollbackFor = {Exception.class}
    )
    @Override
    public void update(SubjectReq subject) {
        if (subject.getId() == null || subject.getId() <= 0){
            throw new ServiceException(GlobalErrorCodeConstants.ID_EMPTY_ERROR);
        }
        SubjectEntity entity = this.getById(subject.getId());
        if (entity == null){
            throw new ServiceException(GlobalErrorCodeConstants.NOT_EXISTS_ERROR);
        }
        BeanUtils.copyProperties(subject, entity);
        this.updateById(entity);
    }

    @Transactional(
            rollbackFor = {Exception.class}
    )
    @Override
    public Long add(SubjectReq subject) {
        subject.setId(null);
        SubjectEntity entity = new SubjectEntity();
        BeanUtils.copyProperties(subject, entity);
        this.save(entity);
        return entity.getId();
    }

    @Override
    public List<SubjectReply> getChildSubject(Long pid) {
        LambdaQueryWrapper<SubjectEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SubjectEntity::getParentId,pid);
        List<SubjectEntity> list = this.list(queryWrapper);
        return list.stream().map(entity -> {
            SubjectReply reply = new SubjectReply();
            BeanUtils.copyProperties(entity,reply);
            reply.setHasChildren(isChildren(entity.getId()));
            return reply;
        }).collect(Collectors.toList());
    }

    //判断是否有下一层数据
    private boolean isChildren(Long subjectId) {
        LambdaQueryWrapper<SubjectEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SubjectEntity::getParentId,subjectId);
        Long count = this.count(queryWrapper);
        return count > 0;
    }

    @Override
    public void exportData(HttpServletResponse response) {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        try {
            String fileName = URLEncoder.encode("课程分类","utf-8");
            response.setHeader("Content-disposition","attachment;filename="+ fileName + ".xlsx");
            //查询数据
            List<SubjectEntity> list = this.list(new LambdaQueryWrapper<SubjectEntity>().orderByDesc(SubjectEntity::getId));
            List<SubjectExcDto> collect = list.stream().map(x -> {
                SubjectExcDto excDto = new SubjectExcDto();
                BeanUtils.copyProperties(x, excDto);
                return excDto;
            }).collect(Collectors.toList());
            EasyExcel.write(response.getOutputStream(),SubjectExcDto.class)
                    .sheet("sheet1").doWrite(collect);
        } catch (IOException e) {
            //log.error("课程分类导出失败:{}",e);
            throw new ServiceException(GlobalErrorCodeConstants.FILE_DOWNLOAD_ERROR);
        }
    }

    @Override
    public List<ExcErrorInfoDto> importData(MultipartFile file) {
        List<ExcErrorInfoDto> errorInfoDtos = new ArrayList<>();
        try {
            EasyExcel.read(file.getInputStream(),SubjectExcDto.class,new ReadExcelListener(batchSize,this,errorInfoDtos))
                    .sheet().doRead();
            return errorInfoDtos;
        } catch (IOException e) {
           // log.error("课程分类导入失败:{}",e);
            throw new ServiceException(GlobalErrorCodeConstants.FILE_UPLOAD_ERROR);
        }
    }

}